#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

int confd = -1;

void init_client(const char* ip)
{
    // 创建套接字
    confd = socket(AF_INET, SOCK_STREAM, 0);
    if (confd == -1)
    {
        perror("socket error");
        exit(1);
    }

    // 连接服务端
    // 先准备服务端的通信地址
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(10010);
    addr.sin_addr.s_addr = inet_addr(ip);
    
    // 再连接
    int r = connect(confd, (struct sockaddr*)&addr, sizeof(addr));
    if (r == -1)
    {
        perror("connect error");
        exit(1);
    }

    printf("connet server ok \n");
}

int connect_and_join_room(const char* server_ip) 
{
    // 连接服务器
    init_client(server_ip);
    
    // 输入房间号
    char room_buf[32] = {0};
    printf("请输入房间号 (只能为0~99): \n");
    if (fgets(room_buf, sizeof(room_buf), stdin) == NULL) 
    {
        printf("未输入房间号，客户端退出\n");
        exit(1);
    }
    // 去除换行符
    room_buf[strcspn(room_buf, "\n")] = 0;
    write(confd, room_buf, strlen(room_buf));
    return 0;
}

void* recv_thread(void* arg)
{
    int fd = *(int*)arg;
    char buf[1024];
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        int r = read(fd, buf, sizeof(buf)-1);
        if (r > 0)
        {
            printf("%s \n", buf);
            fflush(stdout);
        }
        else if (r == 0)
        {
            printf("服务器已关闭连接\n");
            exit(0);
        }
        else
        {
            perror("read error");
            exit(1);
        }
    }
    return NULL;
}

int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s server_ip \n", argv[0]);
        exit(1);
    }
    const char* server_ip = argv[1];

    while (1) 
    {
        connect_and_join_room(server_ip);
        pthread_t tid;
        pthread_create(&tid, NULL, recv_thread, &confd);

        // 显示帮助信息
        printf("\n=== 聊天室使用说明 ===\n");
        printf("输入消息进行聊天\n");
        printf("特殊命令:\n");
        printf("  /online  - 查看当前房间在线人数\n");
        printf("  /rooms   - 查看所有房间在线人数\n");
        printf("  /users   - 查看当前房间所有在线用户IP\n");
        printf("  /history - 查看聊天记录\n");
        printf("  /quit    - 退出当前房间\n");
        printf("  /help    - 显示此帮助信息\n");
        printf("=====================\n\n");

        int quit_flag = 0;
        while (!quit_flag) 
        {
            // 从键盘输入数据
            char msg[100] = {0};
            printf("请输入消息: \n");
            if (fgets(msg, sizeof(msg), stdin) == NULL)
            {
                printf("fgets返回NULL,主线程即将退出\n");
                if (feof(stdin)) 
                {
                    printf("检测到标准输入EOF,主线程退出但不close(confd),read线程继续\n");
                }
                pthread_exit(NULL); // 只退出主线程，不close(confd)
            }
            // 跳过空行输入
            if (strlen(msg) == 0 || strcmp(msg, "\n") == 0) 
            {
                printf("输入为空，不发送\n");
                continue;
            }
            // 去除换行符
            msg[strcspn(msg, "\n")] = 0;
            // 检查特殊命令
            if (strcmp(msg, "/help") == 0) 
            {
                printf("\n=== 聊天室使用说明 ===\n");
                printf("输入消息进行聊天\n");
                printf("特殊命令:\n");
                printf("  /online  - 查看当前房间在线人数\n");
                printf("  /rooms   - 查看所有房间在线人数\n");
                printf("  /users   - 查看当前房间所有在线用户IP\n");
                printf("  /history - 查看聊天记录\n");
                printf("  /quit    - 退出当前房间\n");
                printf("  /help    - 显示此帮助信息\n");
                printf("=====================\n\n");
                continue;
            }
            if (strcmp(msg, "/quit") == 0) 
            {
                printf("您已退出当前房间。\n");
                close(confd);
                pthread_cancel(tid); // 终止接收线程
                pthread_join(tid, NULL);
                quit_flag = 1;
                break;
            }
            // 发送消息到服务器
            int w = write(confd, msg, strlen(msg));
            if (w == -1) {
                perror("write error");
                break;
            }
        }
    }
    return 0;
}
